import {
  Shader,
  ShaderData,
  ShaderProperty,
  ShaderPool,
  ShaderProgram,
  ShaderProgramPool,
  ShaderMacro,
  ShaderMacroCollection,
  ShaderDataGroup,
  ShaderLib
} from "@nirvana/shaders";
import { Vector3, Matrix4 } from "@nirvana/math";

import { WebGLCanvas } from "@nirvana/canvas";
import { VertexBufferData, IndexBufferData, DataElement } from "@nirvana/core";

const shaderMacroCollection: ShaderMacroCollection = new ShaderMacroCollection();
console.log(shaderMacroCollection);
const colorShaderData: ShaderData = new ShaderData(ShaderDataGroup.Material);
console.log(ShaderDataGroup, colorShaderData);
const pool: ShaderProgramPool = new ShaderProgramPool();

// 使用使用 Canvas
let canvas = document.getElementById("engine-nirvana");
const webCanvas = new WebGLCanvas(canvas, {});
const engine = webCanvas.engine;
const gl = engine.gl;

const cVS = `
attribute vec3 position;
uniform mat4 rotateMatrix;
varying vec3 vColor;
void main(void) { 
  gl_Position = rotateMatrix * vec4(position, 1.);
  vColor = vec3(1.0,1.0,1.0);
}
`;
const cFS = `
varying vec3 vColor;
void main(void) {
  gl_FragColor = vec4(vColor, 1.);
}`;
const colorDemo = Shader.create("colorDemo", cVS, cFS);
console.log(colorDemo, Shader.find("colorDemo"));

const program: ShaderProgram = colorDemo.getShaderProgram(engine.gl, shaderMacroCollection, pool);
console.log("color", program);

const vertices: number[] = [
  -0.5, -0.5, -0.5,  0.5, -0.5,-0.5, 0.5, 0.5,-0.5, -0.5, 0.5,-0.5,
  -0.5, -0.5,  0.5,  0.5, -0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5,
  -0.5, -0.5, -0.5, -0.5, 0.5,-0.5, -0.5, 0.5, 0.5, -0.5,-0.5, 0.5,
   0.5, -0.5, -0.5,  0.5, 0.5,-0.5, 0.5, 0.5, 0.5, 0.5,-0.5, 0.5,
  -0.5, -0.5, -0.5, -0.5,-0.5, 0.5, 0.5,-0.5, 0.5, 0.5,-0.5,-0.5,
  -0.5,  0.5, -0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5,-0.5, 
];

const indices: number[] = [
  0,1,2, 0,2,3, 4,5,6, 4,6,7,
  8,9,10, 8,10,11, 12,13,14, 12,14,15,
  16,17,18, 16,18,19, 20,21,22, 20,22,23
];
const nVertex: number[] = [];
let len = vertices.length / 3;
// 1、for with index
const edge = [0, 0],
  edges = {};
for (let i = 0; i < len; i += 3) {
  for (let j = 0; j < 3; j++) {
    const edge1 = indices[i + j];
    const edge2 = indices[i + ((j + 1) % 3)];
    console.log(edge1, edge2);
    edge[0] = Math.min(edge1, edge2); // sorting prevents duplicates
    edge[1] = Math.max(edge1, edge2);
    const key = edge[0] + "," + edge[1];

    if (edges[key] === undefined) {
      edges[key] = { index1: edge[0], index2: edge[1] };
    }
  }
}

for (const key in edges) {
  const e = edges[key];
  let i: number = e.index1 * 3;
  let j: number = e.index2 * 3;
  nVertex.push(vertices[i], vertices[i + 1], vertices[i + 2]);
  nVertex.push(vertices[j], vertices[j + 1], vertices[j + 2]);
}

// // 2、with non-indexed
// for (let i = 0; i < len; i++) {
//   for (let j = 0; j < 3; j++) {
//     const index1 = 3 * i + j;
//     const index2 = 3 * i + ((j + 1) % 3);
//     nVertex.push(vertices[index1], vertices[index1 + 1], vertices[index1 + 2]);
//     nVertex.push(vertices[index2], vertices[index2 + 1], vertices[index2 + 2]);
//   }
// }

const vBuffer = new VertexBufferData(new Float32Array(nVertex), [
  new DataElement("position", 3, gl.FLOAT, false, 0, 0)
]);
const iBuffer = new IndexBufferData(new Uint16Array(indices));
vBuffer.create(gl);
// cBuffer.create(gl);
// iBuffer.create(gl);

console.log(nVertex);

const shaderData: ShaderData = new ShaderData(ShaderDataGroup.Material);
console.log(ShaderDataGroup, shaderData);

let r = 0;
const axis = new Vector3(0.8, 1.0, 0.5);
const rotateMatrix = Matrix4.e;
engine.update = (gl) => {
  r += 0.01;
  rotateMatrix.rotationAxisAngle(axis, r);
  // console.log('--');
  gl.clearColor(0.0, 0.0, 0.0, 1.0);
  // 用上面指定的颜色清除缓冲区
  gl.clear(gl.COLOR_BUFFER_BIT);
  gl.enable(gl.DEPTH_TEST);
  // gl.enable(gl.CULL_FACE);
//   gl.enable(gl.BLEND);
// gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
  // 颜色 start 三
  program.bind();
  vBuffer.upload(program._glProgram, gl);
  // cBuffer.upload(program._glProgram, gl);
  shaderData.setMatrix("rotateMatrix", rotateMatrix);
  program.uploadAll(program.otherUniformBlock, shaderData);
  iBuffer.upload(gl);
  gl.drawArrays(gl.LINES, 0, nVertex.length / 3);
  // gl.drawElements(gl.LINES, nIndices.length, gl.UNSIGNED_SHORT, 0);
  // iBuffer.draw(gl);
};
